#include "sock.hpp"
#include "util.hpp"
#include <time.h>
#include <vector>
#include <unordered_map>
#include <utility>
#include <algorithm> 
#include <functional>
#include <poll.h>
class pollserver{
    using func_t = std::function<std::string(std::string)>;
    const static int num = 1024;
    const static int defaultfd = -1;
public:
    pollserver(const uint16_t port,func_t buildingresponse) :_port(port),_listensock(-1),_func(buildingresponse)
    {}
    void init(){
        _listensock = Sock::GetListenSock();
        Sock::Setsockopt(_listensock); //需要在bind之前设置
        Sock::Bind(_listensock,_port);
        Sock::Listen(_listensock,5);
        _fdlist = new pollfd[num];
        for(int i = 0 ; i < num ; i++){
            _fdlist[i].fd = defaultfd;
            _fdlist[i].events = 0;
            _fdlist[i].revents = 0;
        }
        insert(_listensock);

    }
    // void Print(){
    //     std::cout<<"fd:";
    //     for(auto& x: _fdlist){
    //         std::cout<<" "<<x->fd<<" "<<x->events;
    //     }
    //     std::cout<<std::endl;
    // }
    void start(){
        for(;;){
            // fd_set fds;
            // FD_ZERO(&fds);
            // fds_set(fds);
            // // timeval timeout = {1,0};
            // int maxfd = findmaxfd(sockfds);
            // int ret = select(maxfd+1,&fds,nullptr,nullptr,nullptr);
            int ret = poll(_fdlist,num,-1);
            logmessage(DEBUG,"测试1");
            if(ret > 0){
                //等待成功
                logmessage(NORMAL,"wait is succuss");
                handler();
            }else if(ret == 0){
                //超时
                logmessage(NORMAL,"wait is time_over");
            }else{
                logmessage(FATAL,"poll faild");
                exit(POLLERR);
                //select调用失败
            }
    
        }

    }
    ~pollserver(){
        if(_listensock > -1 )   close(_listensock);
        delete[] _fdlist;
    }
private:
    void insert(int newfd){
        int i = 0 ;
        for(; i < num ; i++){
            if(_fdlist[i].fd != defaultfd) continue;
            break;
        }
        if(i == num){
            close(newfd);
            logmessage(WARING,"platz is voll ,please  wait");
            return;
        }else{
            _fdlist[i].fd = newfd;
            _fdlist[i].events = POLLIN;
            _fdlist[i].revents = 0;
        }
    }

    void handler(){
        std::cout<<"成功触发fd: ";
        for(int i = 0 ; i < num; i++){
            pollfd* x = _fdlist+i;
            if(x->revents & POLLIN){
                std::cout<<x->fd<<" ";
                if(x->fd == _listensock){
                    //监听事件触发
                    std::string ip;
                    uint16_t port;
                    int newfd = Sock::Accept(_listensock,&ip,&port);
                    insert(newfd);
                    //std::cout<<ip<<port;
                }else{
                    //读事件触发
                    readhander(x,i);
                }
            }
        }
        std::cout<<std::endl;
    }
    void readhander(pollfd* fdpoint,int pos){
        char buffer[1024];
        //这样读取是有问题的,因为无法读取到一个完整的报文!!!(需要自己订应用层协议),暂时这样读取
        memset(buffer,0,sizeof buffer);
        ssize_t r = read(fdpoint->fd,buffer,sizeof buffer);
        if(r > 0){
            buffer[r] = 0;
            std::cout<<"server ehco#"<<buffer<<std::endl;
        }else if(r == 0){
            close(fdpoint->fd);
            _fdlist[pos].fd = defaultfd;
            _fdlist[pos].events = 0;
            _fdlist[pos].revents = 0;
            logmessage(NORMAL,"client quit");
            return;
        }else{
            close(fdpoint->fd);
            _fdlist[pos].fd = defaultfd;
            _fdlist[pos].events = 0;
            _fdlist[pos].revents = 0;
            logmessage(ERROR,"read faild");
            return;
        }
        //构建response
        //buffer[r-1] = '\n';
        std::string response = _func(buffer);
        //write 下面的代码有问题,但是暂时不考虑
        write(fdpoint->fd,response.c_str(),response.size());
    }
private:
    uint16_t _port;
    int _listensock;
    pollfd* _fdlist;
    func_t _func;
};